using UnityEngine;

[ExecuteInEditMode]
public class UVOffsetTracker : MonoBehaviour
{
	public static string GlobalLastPackName;

	private string _lastPackName;

	public string PackName;

	private int _index;

	public int Index;

	private bool _isUseUV2;

	public bool IsUseUV2;

	private MeshFilter _meshFilter;

	public bool IsCacheOnFirstCalc;

	public bool IsSharedMesh;

	[HideInInspector]
	public UVLayer[] UVLayers;

	private int _currentLayerIndex;

	private Vector2 _backTextureSize;

	public Mesh CachedSharedMesh;

	[HideInInspector]
	public ColorChanger ColorChanger;

	[HideInInspector]
	public Vector2[] CurrentUV;

	private void Start()
	{
		ColorChanger = GetComponent<ColorChanger>();
		if (ColorChanger != null)
		{
			ColorChanger.UVOffsetTracker = this;
		}
		_meshFilter = GetComponent<MeshFilter>();
		if (!Application.isPlaying)
		{
			CachedSharedMesh = null;
		}
		CheckMesh();
		if (UVLayers == null || UVLayers.Length == 0)
		{
			UVLayers = new UVLayer[2];
		}
		if (UVOffsetManager.Instance.PackDict == null || !UVOffsetManager.Instance.PackDict.ContainsKey(PackName))
		{
			UVOffsetManager.Instance.MakePackFromList();
		}
		UVLayers[0] = UVOffsetManager.Instance.PackDict[PackName].LayerUV1;
		UVLayers[1] = UVOffsetManager.Instance.PackDict[PackName].LayerUV2;
		Mesh mesh = CloneSharedMesh();
		for (int i = 0; i < 2; i++)
		{
			if (!UVLayers[i].UVMeshInfoDict.ContainsKey(base.gameObject.name))
			{
				UVLayers[i].UVMeshInfoDict.Add(base.gameObject.name, new UVMeshInfo());
			}
			if (!UVLayers[i].UVMeshInfoDict[base.gameObject.name].WasCalc)
			{
				UVLayers[i].UVMeshInfoDict[base.gameObject.name].OriginalUV = ((i != 0) ? mesh.uv2 : mesh.uv);
			}
			CalcUVOffset(mesh, i);
		}
		_meshFilter.mesh = mesh;
		SetIndex(Index, IsUseUV2);
	}

	private void CheckMesh()
	{
		if (_meshFilter != null && _meshFilter.sharedMesh == null)
		{
			MeshCollider component = GetComponent<MeshCollider>();
			if (component != null)
			{
				_meshFilter.sharedMesh = component.sharedMesh;
			}
		}
		if (CachedSharedMesh == null && _meshFilter != null)
		{
			CachedSharedMesh = ((!(ColorChanger != null)) ? _meshFilter.sharedMesh : ColorChanger.CachedSharedMesh);
		}
	}

	private Mesh CloneSharedMesh()
	{
		if (_meshFilter == null)
		{
			_meshFilter = GetComponent<MeshFilter>();
		}
		CheckMesh();
		Mesh cachedSharedMesh = CachedSharedMesh;
		Mesh mesh = new Mesh();
		mesh.vertices = cachedSharedMesh.vertices;
		mesh.normals = cachedSharedMesh.normals;
		mesh.tangents = cachedSharedMesh.tangents;
		mesh.colors = ((!(ColorChanger == null)) ? ColorChanger.Colors : cachedSharedMesh.colors);
		mesh.uv = cachedSharedMesh.uv;
		mesh.uv2 = cachedSharedMesh.uv2;
		mesh.uv2 = cachedSharedMesh.uv2;
		mesh.triangles = cachedSharedMesh.triangles;
		return mesh;
	}

	public void SetIndex(int iIndex, bool iIsUseUV2)
	{
		_isUseUV2 = iIsUseUV2;
		IsUseUV2 = _isUseUV2;
		_currentLayerIndex = (_isUseUV2 ? 1 : 0);
		_index = Mathf.Clamp(iIndex, 0, UVLayers[_currentLayerIndex].RecordsUV.Length - 1);
		Index = _index;
		if (IsSharedMesh)
		{
			OnIndexChanged(_meshFilter.sharedMesh);
			return;
		}
		Mesh mesh = CloneSharedMesh();
		OnIndexChanged(mesh);
		_meshFilter.mesh = mesh;
	}

	private void CalcUVOffset(Mesh iMesh, int iLayerIndex)
	{
		if (UVLayers[iLayerIndex].RecordsUV.Length == 0 || iMesh == null)
		{
			BCWDebug.LogError("Setup correct mesh on object " + base.gameObject.name);
			return;
		}
		_backTextureSize = new Vector2(1f / (float)GetComponent<Renderer>().sharedMaterial.mainTexture.width, 1f / (float)GetComponent<Renderer>().sharedMaterial.mainTexture.height);
		if (!UVLayers[iLayerIndex].UVMeshInfoDict[base.gameObject.name].WasCalc)
		{
			UVLayers[iLayerIndex].UVMeshInfoDict[base.gameObject.name].WasCalc = true;
			UVLayers[iLayerIndex].CenterUV = new Vector2((float)UVLayers[iLayerIndex].RecordsUV[0].X * _backTextureSize.x, (float)UVLayers[iLayerIndex].RecordsUV[0].Y * _backTextureSize.y);
			UVLayers[iLayerIndex].BackSizeUV = new Vector2(1f / ((float)UVLayers[iLayerIndex].RecordsUV[0].Width * _backTextureSize.x), 1f / ((float)UVLayers[iLayerIndex].RecordsUV[0].Height * _backTextureSize.y));
			UVLayers[iLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV = new Vector2[(iLayerIndex != 1) ? iMesh.uv.Length : iMesh.uv2.Length];
			for (int i = 0; i < UVLayers[iLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV.Length; i++)
			{
				UVLayers[iLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV[i] = UVLayers[iLayerIndex].UVMeshInfoDict[base.gameObject.name].OriginalUV[i] - UVLayers[iLayerIndex].CenterUV;
			}
		}
	}

	private void OnIndexChanged(Mesh iMesh)
	{
		if (UVLayers[_currentLayerIndex].RecordsUV[_index].WasCalc)
		{
			CurrentUV = UVLayers[_currentLayerIndex].RecordsUV[_index].UV;
			iMesh.uv = CurrentUV;
			return;
		}
		Vector2 vector = new Vector2((float)UVLayers[_currentLayerIndex].RecordsUV[_index].X * _backTextureSize.x, (float)UVLayers[_currentLayerIndex].RecordsUV[_index].Y * _backTextureSize.y);
		Vector2 vector2 = new Vector2((float)UVLayers[_currentLayerIndex].RecordsUV[_index].Width * _backTextureSize.x, (float)UVLayers[_currentLayerIndex].RecordsUV[_index].Height * _backTextureSize.y);
		Vector2 vector3 = new Vector2(vector2.x * UVLayers[_currentLayerIndex].BackSizeUV.x, vector2.y * UVLayers[_currentLayerIndex].BackSizeUV.y);
		Vector2[] array = new Vector2[UVLayers[_currentLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV.Length];
		for (int i = 0; i < UVLayers[_currentLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV.Length; i++)
		{
			array[i] = vector + RotatePoint(new Vector2(UVLayers[_currentLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV[i].x * vector3.x, UVLayers[_currentLayerIndex].UVMeshInfoDict[base.gameObject.name].OffsetsUV[i].y * vector3.y), UVLayers[_currentLayerIndex].RecordsUV[_index].Angle);
		}
		if (IsCacheOnFirstCalc)
		{
			UVLayers[_currentLayerIndex].RecordsUV[_index].UV = array;
			UVLayers[_currentLayerIndex].RecordsUV[_index].WasCalc = true;
		}
		CurrentUV = array;
		iMesh.uv = array;
	}

	private Vector2 RotatePoint(Vector2 iPoint, int iAngle)
	{
		switch (iAngle)
		{
		case 90:
			return new Vector2(iPoint.y, 0f - iPoint.x);
		case 180:
			return new Vector2(0f - iPoint.x, 0f - iPoint.y);
		case 270:
			return new Vector2(0f - iPoint.y, iPoint.x);
		default:
			return iPoint;
		}
	}
}
